package com.egao.platform.common.utils;

import cn.hutool.core.img.ImgUtil;
import com.egao.platform.common.Constants;
import com.egao.platform.common.core.JsonResult;
import org.apache.tika.Tika;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 文件上传下载工具类
 * Created by wangfan on 2018-12-14 08:38
 */
public class FileUploadUtil {
    // 文件上传的目录
    private static final String UPLOAD_FILE_DIR = Constants.UPLOAD_DIR + "file/";
    // 缩略图存放的目录
    private static final String UPLOAD_SM_DIR = Constants.UPLOAD_DIR + "thumbnail/";

    /**
     * 上传文件
     *
     * @param file MultipartFile
     * @return 示例：{"code": 0, "msg": "", "url": "", "fileName": ""}
     */
    public static JsonResult upload(MultipartFile file) {
        String path;  // 文件保存路径
        // 文件原始名称
        String originalFileName = file.getOriginalFilename();
        String suffix = originalFileName.substring(originalFileName.lastIndexOf(".") + 1);  // 获取文件后缀
        File outFile;
        if (Constants.UPLOAD_UUID_NAME) {  // uuid命名
            path = getDateDir() + UUID.randomUUID().toString().replaceAll("-", "") + "." + suffix;
            outFile = new File(UPLOAD_FILE_DIR + path);
        } else {  // 使用原名称，存在相同着加(1)
            String prefix = originalFileName.substring(0, originalFileName.lastIndexOf("."));  // 获取文件名称
            path = getDateDir() + originalFileName;
            outFile = new File(UPLOAD_FILE_DIR, path);
            int sameSize = 1;
            while (outFile.exists()) {
                path = getDateDir() + prefix + "(" + sameSize + ")." + suffix;
                outFile = new File(UPLOAD_FILE_DIR, path);
                sameSize++;
            }
        }
        try {
            if (!outFile.getParentFile().exists()) {
                outFile.getParentFile().mkdirs();
            }
            file.transferTo(outFile);
        } catch (Exception e) {
            e.printStackTrace();
            return JsonResult.error("上传失败").put("error", e.getMessage());
        }
        return JsonResult.ok("上传成功").put("url", path).put("fileName", originalFileName);
    }

    /**
     * 上传文件base64格式
     *
     * @param base64 base64编码字符
     * @return 示例：{"code": 0, "msg": "", "url": ""}
     */
    public static JsonResult upload(String base64) {
        if (base64 != null && !base64.trim().isEmpty()) {
            String suffix = base64.substring(11, base64.indexOf(";"));  // 获取文件格式
            String path = getDateDir() + UUID.randomUUID().toString().replaceAll("-", "") + "." + suffix;
            File outFile = new File(UPLOAD_FILE_DIR, path);
            if (!outFile.getParentFile().exists()) {
                outFile.getParentFile().mkdirs();
            }
            FileOutputStream out = null;
            try {
                byte[] bytes = Base64.getDecoder().decode(base64.substring(base64.indexOf(";") + 8).getBytes());
                out = new FileOutputStream(outFile);
                int off = 0, len = 1024 * 8;
                while (off < bytes.length) {
                    out.write(bytes, off, len);
                    off += len;
                }
                out.flush();
            } catch (Exception e) {
                e.printStackTrace();
                return JsonResult.error("上传失败").put("error", e.getMessage());
            } finally {
                if (out != null) {
                    try {
                        out.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
            return JsonResult.ok("上传成功").put("url", path);
        }
        return JsonResult.error("上传失败");
    }

    /**
     * 按照日期分存放目录
     */
    public static String getDateDir() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd/");
        return sdf.format(new Date());
    }

    /**
     * 预览文件
     */
    public static void preview(String path, HttpServletResponse response) {
        File file = new File(UPLOAD_FILE_DIR, path);
        if (!file.exists()) {
            outNotFund(response);
            return;
        }
        // 支持word、excel预览
        if (OpenOfficeUtil.canConverter(path)) {
            file = OpenOfficeUtil.converterToPDF(path);
            if (file != null) {
                response.setContentType("application/pdf");
            } else {
                outNotFund(response);
                return;
            }
        } else {
            String contentType = getFileType(file);  // 获取文件类型
            if (contentType != null) {
                response.setContentType(contentType);
            } else {
                setDownloadHeader(response, file.getName());
            }
        }
        try {
            output(file, response.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 下载文件
     */
    public static void download(String path, HttpServletResponse response) {
        File file = new File(UPLOAD_FILE_DIR, path);
        if (!file.exists()) {
            outNotFund(response);
            return;
        }
        setDownloadHeader(response, file.getName());
        try {
            output(file, response.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 预览缩略图
     */
    public static void thumbnail(String path, HttpServletResponse response) {
        // 如果是图片并且缩略图不存在则生成
        File smFile = new File(UPLOAD_SM_DIR, path);
        if (!smFile.exists() && isImgFile(smFile)) {
            // 大于100kb生成100kb的缩略图
            File file = new File(UPLOAD_FILE_DIR, path);
            long fileSize = file.length();
            if ((fileSize / 1024) > 100) {
                smFile.getParentFile().mkdirs();
                try {
                    ImgUtil.scale(file, smFile, 100f / (fileSize / 1024f));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else {
                preview(UPLOAD_FILE_DIR + path, response);
                return;
            }
        }
        preview(smFile.getAbsolutePath(), response);
    }

    /**
     * 输出文件流
     */
    public static void output(File file, OutputStream os) {
        BufferedInputStream is = null;
        try {
            is = new BufferedInputStream(new FileInputStream(file));
            byte[] bytes = new byte[1024 * 256];
            int len;
            while ((len = is.read(bytes)) != -1) {
                os.write(bytes, 0, len);
            }
            os.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 删除文件
     */
    public static boolean delete(String path) {
        File file = new File(UPLOAD_FILE_DIR, path);
        if (file.delete()) {
            new File(UPLOAD_SM_DIR, path).delete();
            return true;
        }
        return false;
    }

    /**
     * 获取文件类型
     */
    public static String getFileType(File file) {
        String contentType = null;
        try {
            contentType = new Tika().detect(file);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return contentType;
    }

    /**
     * 判断是否是图片类型
     */
    public static boolean isImgFile(File file) {
        String contentType = getFileType(file);
        return contentType != null && contentType.startsWith("image/");
    }

    /**
     * 设置下载文件的header
     */
    public static void setDownloadHeader(HttpServletResponse response, String fileName) {
        response.setContentType("application/force-download");
        try {
            fileName = URLEncoder.encode(fileName, "utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        response.setHeader("Content-Disposition", "attachment;fileName=" + fileName);
    }

    /**
     * 输出文件不存在
     */
    public static void outNotFund(HttpServletResponse response) {
        response.setStatus(HttpServletResponse.SC_NOT_FOUND);
        outMessage("404 Not Found", response);
    }

    /**
     * 输出错误信息
     */
    public static void outMessage(String message, HttpServletResponse response) {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter writer;
        try {
            writer = response.getWriter();
            writer.write("<!doctype html>");
            writer.write("<title>" + message + "</title>");
            writer.write("<h1 style=\"text-align: center\">" + message + "</h1>");
            writer.write("<hr/><p style=\"text-align: center\">Egao File Server</p>");
            writer.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
